//
//  ReadMe.swift
//  人员分配等问题介绍
//
//  Created by Apple on 16/10/22.
//  Copyright © 2016年 Apple. All rights reserved.
//


/*
    第十二天 
 
            - 新浪微博数据缓存流程
                - 检查本地是否有缓存数据
                - 如果有缓存数据那么直接使用本地的缓存数据
                - 如果没有缓存数据那么直接使用网络请求新浪微博数据
                - 网络数据请求完成以后缓存新浪微博数据到本地
                - 新浪微博数据缓存成功后直接使用网络请求后的新浪微博数据
 
 
 
 
            - 新浪微博表的创建分析
                -   微博 id -> 根据微博 id 判断本地是否有缓存数据
                -   微博内容(整个微博数据-> 微博字典) -> 把数据转成二进制插入到表里面
                -   用户 id  -> 区分不同用户下的缓存数据
                -   插入微博数据时间  -> 根据缓存时间删除缓存数据
 
 
 
            - 富文本根据范围替换保存的原因
        0-7, 7-7
        xx
 
            - 集成 YYText
                - 把 UILabel 换成 YYLabel
                    -- 遇到自己创建的富文本表情显示不出来
                        --解决办法 使用YYText 方式创建富文本
 
                             -//  使用 yytext 方式创建表情富文本
                             let image = UIImage(named: emoticon.fullPath!)!
                             let attributedStr = NSAttributedString.yy_attachmentString(withEmojiImage: image, fontSize: HMNormalFontSize)!
 
                - 显示高亮效果
                     -  let textHighlight = YYTextHighlight()
                     //  高亮点击的高亮背景色
                     let bgColor = UIColor(red: 177 / 255, green: 215 / 255, blue: 255 / 255, alpha: 1)
                     let textBorder = YYTextBorder(fill: bgColor, cornerRadius: 3)
                     //  设置边框内间距
                     textBorder.insets = UIEdgeInsets(top: 1, left: 0, bottom: 0, right: 0)
                     textHighlight.setBackgroundBorder(textBorder)
                     //  设置富文本高亮效果
                     resultAttributedStr.yy_setTextHighlight(textHighlight, range: highlightRange)
 
 
                - 点击高亮效果获取对应的字符串
 
                     - //  点击高亮效果执行的闭包
                     //  (view, attributedString, range, rect)
                     //  1. view : 显示富文本的容器, YYLabel
                     //  2. attributedString: 显示的富文本
                     //  3. range  : 点击高亮的范围
                     //  4. rect:  点击的高亮的区域
                     contentLabel.highlightTapAction = { (view, attributedString, range, rect) -> Void in
                     //  根据高亮的范围获取对应的字符串
                     let text = (attributedString.string as NSString).substring(with: range)
                     print(text)
                     
                     
                     }
 
 
 
 */


//  ==============================
/*
    第十一天
 
        - 最近表情实现思路分析
            - 1. 把表情添加到最近表情第一元素位置
            - 2. 把最近这组表情进行归档
            - 3. 程序启动的时候最近表情有数据需要进行解档
 
 
        - 图片转成富文本的操作流程
            - 1. 根据图片的全路径创建 UIImage 对象
            - 2. 根据 UIImage 对象创建文本附件(NSTextAttachment)
            - 3. 根据文本附件创建富文本(NSAttributedString)
            - 4. 设置富文本
 
 
 */




//  ====================================


/*
 
    第十天
 
        - 表情 toolbar 联动分析
            1. 监听表情视图(collectionview)的滚动
            2. 获取哪个 cell 在 collectionview 的内容中心显示
            3. 根据内容的中心点获取对应的 indexPath
            4. 获取 indexPath 对应的 section
            5. 根据这个 section 让 toolbar 选中指定的按钮
 
        - 表情键盘数据结构分析
 
            1. 每页上面显示20个表情按钮 -> [Model]
            2. 每种表情有可能有多页显示 ->  [[Model], [Model]]
            3. 表情视图需要知道有多少种表情 -> [ [[Model], [Model]], [[Model], [Model]], [[Model], [Model]], [[Model], [Model]] ]
 
 */




// ==============================================

/*
 
 - 第八天时间格式化逻辑处理
    - 判断时间是否是今年
        - 判断是否是今天
            - 判断是否是1分钟之前
                - 刚刚
            - 判断是否是1小时之前
                - xx 分钟前
            - 其它
                - xx 小时前
 
 
        - 判断是否是昨天
            - 昨天 08:10
        - 其它
            - 10-30 10:20
 
    - 不是今年
        2015-10-10 10:10
 
 
 
 
 
 
  ===============================================================
 - 第七天
        - 第七天下午内容回顾
            - 自定义菊花UIActivityIndicatorView 作为 上啦记载更多的表示
                - 作为 tableView 的 footView
                - 如何动画
                    - 设置代理 监听tableView 滚动到最后一个 cell 开始动画
            - 改变 statusListViewModel 的请求数据的函数(添加了一个参数 isPullup) 
                - 判断到底是下拉刷新 还是上啦加载更多
            - 改变 NetworkTools 中请求首页数据的方法 (sinceId 和 maxId)
            - 调度组
                - 监听我们想监听的子线程事件是否处理完成 统一回调 
 
            - 单张图片缓存
                - 当我们从网络请求回来微博的数据
                - 遍历每次请求回来的数据
                - 遍历数组 得到对应的 statusViewModel 中的 pic_urls.count
 
                - 不管是原创微博 图片== 1  还是转发微博的图片==1 我们均下载
                - 使用 SDWebImage 来下载图片
                - 调度组统一监听图片下载完成 执行闭包
                - 刷新 UI
                - 当数据传递到配图视图
                    - 如果你是一张图片 
                        - 如果 image 从缓存中可以取到
                            - 重新设置 itemSize 和配图视图的大小
                    - 反之 
                        - 按照我们正常的设置itemSize 和配图视图的大小
                    - 注意: 如果单张图片没有下载成功 我们需要他还继续下载 但是这个配图的大小 和 itemSize 需要程序员自己制定
 
                - 如果后期处理单张图片 过宽  过窄 过长 需要程序员按照产品经理的要求改
                - 分析下拉刷新控件
                    - 继承 UIContorl
                    - 添加到 tablView 身上
                    - 需要人为给设置一个控件的高度
                    - 当外界使用时候 只需要 addSubViews 就能直接显示
                    - 控件的 frame x = 0  y = - 控件的高度

        - 分析自定义下拉刷新控件
            - 使用什么做下拉刷新控件 -> 继承谁 -> UIControl
            - 放在谁身上  -> tableView 身上  frame = w = 屏幕 ,h 自己设置 x = 0  y -自己设置
            - 监听 -> 3个状态
                - 正常中 (不松手 ) -> 控件没有显示完全 或者根本没有显示
                - 下拉中 (不松手 ) -> 控件全部显示出来
                - 刷新中 
                    - 满足你当前是下拉中 
                    - 你还要松手了

        - 分析单张图片缓存问题
            - 为什么缓存 -> 我们需要图片大小 来确定 itemSize 和 pictureView 的 size
            - 解决方案: 在我们请求数据回来后 我们就要下载图片
                    -> 判断
                        - 原创微博 -> 如果 count == 1 才下载 
                        - 转发微博 -> 如果 count == 1 才下载
                        - 其他均不会下载
 
 
        - 上午内容回顾
            - 自定义配图视图(collectionView)
                - 为什么? 原创微博和转发微博都需要他 所以进行自定义
                        - 需要满足当前的业务需求
                - 设置 layout itemSize 间距
                - 定义一个属性 供外界调用 给其赋值 (-> 装有模型的数组)
                - 自定义collectionViewCell
                    - bgImageView
 
            - 原创微博中 可能有配图 也可能没有配图
                    - 通过服务器返回来的数据 数组.count 来判断是否显示配图
                        - 记录约束和卸载对应的约束(原创微博底部)
                        - 如果 count > 0 代表有配图
                            - 赋值
                            - 显示配图
                            - 更新约束 原创微博底部 == 配图底部
                        - 反之 代表没有配图
                            - 隐藏配图
                            - 更新约束 原创微博底部 == 文字底部
 
            - 转发微博 可能有配图 也可能没有配图
                     - 通过服务器返回来的数据 数组.count 来判断是否显示配图
                         - 记录约束和卸载对应的约束(转发微博底部)
                         - 如果 count > 0 代表有配图
                         - 赋值
                         - 显示配图
                         - 更新约束 转发微博底部 == 配图底部
                     - 反之 代表没有配图
                         - 隐藏配图
                         - 更新约束 转发微博底部 == 文字底部
            - 对首页细节优化
                    - 按照业务需求更改颜色
                    - 设置 tableView 相关属性
 
            - 对上拉加载更过和下拉刷新数据分析
 

        - 上拉加载更多 和下拉刷新 参数分析
 
 
            sinceId  maxId
 
 
         - 列表形式 tableView   每一个 cell 显示的一条微博
            - 10
            - 9
            - 8
            - 7
            - 6
            - 如果你是下拉刷新的话 
                - sinceId = 10
                - maxId = 0
            - 如果你是上啦加载更过的话
                - sinceId =  0
                - maxId = 6 - 1
            - 分析得到的 10 或者 5 哪里来的 (保存数组中)
                - sinceId = array.first
                - maxId = array.last
 
            - 为什么服务器就知道我们是下拉刷新或者上啦加载更多
                - 如果你sinceId 和maxId 均为 0  服务器认为你就是拿最新默认数据
            
 ===============================================================
 - 第六天
    - 第六天下午内容回顾
        - 抽取 statuViewModel 帮助 cell 做数据处理
                - statusListViewModel 里面有一个数组 -> [statuViewModel]
                - 当我们请求网络数据成功后 -> 装有 statuModel 的数组
                - 遍历statuModel 的数组 创建statuViewModel 然后给其身上的属性statuModel赋值
                - [statuViewModel]
        - statusListViewModel 告知控制器 HomeVc 刷新 UI
        
 
        - 首页赋值逻辑  
                - 数据 statusListViewModel 中
                - statusListViewModel 给控制器
                - 控制器把数据在给 tableView 
                - tableView 给 cell statuViewModel
                    - cell 分别把数据给
                        - 原创微博statuViewModel
                        - 转发微博statuViewModel
                        - 底部视图statuViewModel
 
        - 原创微博
            - 头像 昵称 等级 认证 时间 来源 内容  -> 图片
        - 转发微博
            - 昵称 内容  -> 图片
        - 底部视图
            - 转发 评论 赞
 
        
    - statuViewModel 会帮原创微博,转发微博,底部视图 作用
        - 原创微博
            - 帮助处理会员等级显示图片逻辑
            - 帮助处理微博用户认证显示图片逻辑
        - 转发微博
            - 帮助显示转发内容 完成 字符串的拼接 @ name: + text
        - 底部视图
            - 帮助处理 转发评论赞 业务逻辑

    - 分析逻辑
 
    - View 级别的 viewModel  帮助 View 做些数据处理
        - model.name  老王   显示在 label -> cell 上  label.text = "你们都是" + model.name (放在 cell 中了)
        - 业务逻辑  -> 你们都是老王
        
        - MVVM
            - ViewModel  ->model 必须有这个属性
            - yourName(你们都是老王) = "你们都是" + model.name
            - cell 上 label label.text == viewModel.yourName
 
 
    - 第六天上午内容回顾
        - 对 OAuth 界面
                - 加了网络指示器
        - 基类懒加载空间 tableView -> 每个控制器中均需要一个 tableView
        - 分析首页使用 tableView  -> 自定义 cell 
            - cell (三大模块 -> 原创 转发 底部视图)
        - 分析首页数据接口 -> get 需要传入 token -> 最外层是字典 得到数组
        - 创建模型 -> statuModel
        - 通过 yymodel 得到对应的数组
        - 使用系统 cell 显示数据
        - 自定义 cell
        - 自定义 originalView (原创微博) -> 搭建 UI
        - 网路请求先抽取到 NetworkTools 中
        - 网路请求再抽取 statusListViewModel -> 帮助首页请求数据和提供数据

    - 首页 cell 分析(三大部分)
        - 原创微博
            - 头像 
            - 昵称
            - 等级
            - 时间
            - 来自
            - 微博正文
            - 认证
            - 配图(可能有可能没有)
        - 转发微博(可能有可能没有)
            - 微博正文
            - 配图(可能有可能没有)
        - 底部视图
            - 转发按钮
            - 评论按钮
            - 点赞按钮
 
 
  ================================================================
  ================================================================
 - 第五天
 
 
        - 第五天下午内容回顾
            - 上午 -> OAuthVc 发送请求(使用的 NetworkTools 中的公共方法)
            - 网络抽取
                 - 01 把OAuthVc 两个 userAccount 和 userInfo 抽取到NetworkTools
                        - 优点: 不把每个接口中的 urlString 和请求参数 暴露在控制器中
                        - 采用什么方式告知控制器最终结果(把闭包作为参数)
                 - 02 把OAuthVc 网络请求方法 抽取到 UserAccountViewModel
                        - 作用: 帮助我们 OAuthVc 请求数据 -> OAutchVc只是想知道请求成功与否
                        - 采用什么方式告知控制器 闭包(只有一个参数 而且为 bool)
                        - 注意我们是在UserAccountViewModel 把两个接口均执行完,OAuthVc值关注最终结果 (把第一个成功的回到用的闭包往第二个接口中传递过去吧 然后最终结果交给第二个接口告知控制器)
            - accessToken (计算型属性)每次调用都需要实时判断
                - 如果UserAccountViewModel 其身上的 userAccountModel == nil 就代表没有登录过 -> accessToken = nil
                - 反之 登录过 
                    - 如果没有过期 -> accessToken = userAccountModel.access_token
                    - 如果过期了 -> accessToken = nil
            - 判断用户是否登录(计算型属性)每次调用都需要实时判断
                    - isLogin = accessToken != nil 就代表登录了
            - 欢迎界面的开发
                    - 搭建 UI
                    - 对 SDWebImage 进行封装
                    - 使用阻尼动画 HeadImageView 嘚瑟起来
                    - 当 HeadImageView 完成 在给'欢迎回来'设置动画
 
            - 切换根控制器
                - 01 首次 app 运行起来
                    - 如果登录了 - rootVc == WelcomeVc
                    - 反之没有登录 - rootVc == MainVc
 
                - 02 如果用户没有登录
                    - 使用通知如何区别出到底是 OAuthVC发送的 还是WelcomeVc ?
                        - 使用 object 
                            - 如果 OAuthVC object == nil
                            - 如果 WelcomeVc object == "welcomeVc"
                    - 引导用户登录
                    - 完成登录后 发送通知 
                    - 告知 appdalegate 切换根控制器为 rootVc == WelcomeVc
                    - 当WelcomeVc动画完成后  
                    - 告知 appdalegate 切换根控制器为 rootVc == MainVc
 

        - 下午内容
            - app 业务流程分析
                - 如果用户没有登录
                    - VisitorVc 
                    - 登录
                    - 登录成功
                    - 欢迎界面
                    - 欢迎界面动画完成后 
                    - 首页(没有访客视图)
                - 如果用户登录了
                    - 欢迎界面
                    - 首页(没有访客视图)

        - 第五天上午内容回顾
            - oauthVc 加载 webView -> loadView  -> view  = webView
            - 微博需要提供一个 urlString  appkey & 回调页 -> 
                - 登陆 open.weibo.com 
                - 注册-> 个人开发者
                - 登陆
                - 微链接 -> 移动应用 -> 继续创建 appkey appsecret
                - 高级信息 -> 设置授权回调页 -> 取消授权回调页
                - 测试信息 -> 该号码是未上下之前使用的号码(未来可能需要加好几个 -> 老板 -> 产品经理)
            - 通过 webView 代理方法 实时监听将要加载的 request
            - 通过一系列的判断 得到 code(授权码)
            - 为了获取 access_token  -> 请求新浪微博的接口 -> access_token, exprice_in uid
            - 需要个人信息信息数据 -> 昵称 和 头像
            - 因为我们当前模型使用的 YYModel 字典转模型(cocoapod 版本 YYModel 需要把的到的数据 response 判断是否可以转成字典 要不返回的为 nil)
            - 由于我们后期会多个模块可能使用当前个人用户信息模型, 而且防止频繁访问网络的接口 获取个人信息数据
                - 解决方式: 采用归档接档
            - 使用 YYModel 提供的 initCoder  encoder 就可以搞定   
            - 保存用户信息对象,而且会多次使用该对象
                - 解决方法:
                    - 使用单例
                    - 当前我们使用开发模式MVVM 模式 -> 数据处理 -> 需要 ViewModel 帮助控制器处理
                    - ViewModel中提供两个方法
                        - saveModel (保存对象到沙盒中)
                        - getModel (获取对象在沙盒中)
                    - 为了防止不频繁操纵沙盒 我们在单例中 创建一个用户信息对象 userAccounModel
                        - userAccounModel 第一次赋值 肯定在 init 方法中 然后调用getModel 完成赋值
                        - 会有 bug 当用户保存完数据后 userAccounModel 为 nil
                            - 解决方法: 在 外界调用saveModel 时候 程序员手动userAccounModel 赋值
            - 自定义类: 可以直接创建 Swift file 文件 需要我们手动 import UIKit 框架
                        class 自定类名{}
                    - 如果需要 init 方法 需要程序员自己手写 但是不需要加 override 和 super.init()
                            - 原因他根本没有父类 -> 孙悟空
 
 
        - 登录微博
        - 微链接 移动开发 - 继续创建
        - 高级信息  授权回调页 和取消授权回调页  
        - 测试信息 关联测试帐号
 
 
 ================================================================
 
 
- 第四天
 
    - 第四天下午内容回顾
        - pod 移除
        - 回顾 oc 单例的写法
        - 学习了 Swift 中单例的写法(和懒加载相似)
        - 回顾了 OC 中 afn 的网络封装 (封装一个公共方法 和 按照业务需求封装不同的请求方法)
        - 学习了 Swift 中 afn 的封装
            - Swift 中的枚举的定义 他不在单单支持以前的 int 类型 可以支持字符串
        - 搭建我们 OAuth 授权界面
        - 介绍 OAuth
 

    - OAuth 授权
        - 翻译 open auth 开发的授权
            - 便捷
            - 安全 
        - 第三方登录
            - 如果你是真机 直接可以完成 应用跳转 然后 得到授权后 直接可以登录你想登录的 app
            - 但是我们是模拟器 但是我们需要上课(OAuth 授权 -> webView 网页版)
 
        - 如果你使用OAuth 而且你开发的 app 需要用户的 name  age token
            - 为什么使用OAuth 授权登录
                - 就拿不到token 就没办法访问微博的公共借口
            - 使用微博登录  微博用户名 和 密码
            - 登录 -> 授权
            - 会给我们 app 一个 用户对应的 code(授权码)
            - 新浪微博 特殊提供一个借口 只要你传入code 我就会给你对应这个人的 token(爱鲜蜂中的 id)
            - 你通过新浪微博给你的token 拼接对应微博请求个人信息的数据借口就可以拿到用户对应的用户信息(name img age sex)
            - 我们 app 中 就有了用户的 name img age sex token
 
        - 如果我们使用的第三方登录 直接是真机 可以跳转到对应的授权 app 中
 
            - 如果支持第三方登录
                    - 注册用户
                        - 使用手机号直接注册
                        - 通过第三方登录返回的个人信息注册openid
 
    - 第四天上午内容总结
        - 按照效果图分析到(首页 消息 发现 我 未登录状态 显示的效果差不多)
            - 解决方案: 抽取基类(VisitorVc) 子控制器继承基类
        - 未登录状态 均要显示访客视图 view
            - loadView  & isLogin
                - false  没有登录 view = visitorView
                - true  登录了  super.loadView()
        - 自定义visitorView(为什么?  MVVM 模式 或者 MVC  应该做到 控制器和 view 隔离 所以要自定义)
                - 按照首页开发(为什么? 首页的控件是最多的)
                - 后期需要消息 发现 我  修改 logo 和 text
                        - 解决方法: 在VisitorVc 创建一个全局的visitorView 供 期继承VisitorVc 子类类调用visitorView 便于 visitorView调用期自己身上的方法
                - visitorView 暴露出的方法 采用的是 可选是参数 为了方便我们辨别出事首页还是其他子控制器
                    - 如果是首页 iconImageView 通过核心动画 叫他转起来
                            - 如果切换控制器或者 app 推到后台 会造成动画移除
                                -解决方法:isRemovedOnCompletion = false
                    - 如果是其他 设置 icon text 和隐藏 圆圈 imageView
        - 设置VisitorVc 导航 按钮
        - 把visitorView 中按钮的点击事件通过闭包抛到其父类 叫其帮助弹出控制器
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    - 访客视图分析
        - 当 app 运行起来 一共创建几个 visitorView 
        - 运行起来 一个4个子控制器  均继承 VisitorVC  -> 就会判断你是否登录 如果没有登录 -> 创建一个 visitorView
        - 你 首页 消息 发现 我 显示的 icon 不同 文字内容不同 (如果是首页的话 有圆圈还要设置动画 其他界面要隐藏圆圈)
            - icon 还有 messageLabel circleImageView  -> visitorView
        - 解决办法 我能不能在visitorView 类中 创建一个外界调用方法 统一在里面设置icon 还有 messageLabel circleImageView
 
 ================================================================
- 第三天
 
 
    - 第三天上午回顾
        - 闭包的循环引用(A-闭包-A)设计和解决方案
            - weak var weakSelf = self   == __weak
            - [weak self]     == __weak
            - [unowed self]   == __unsafe_
        - 项目部署到 osChina 上
            - 使用 ssh 公钥
            - 克隆项目
            - 添加忽略文件(一定要先添加)
            - 创建项目(对项目做一些相关的设置)
            - 通过业务需求 明细文件夹(MVVM)
            - MVVM
                - Model
                - View (view controller)
                - ViewModel
            - 创建主控制器(MainVc)
                    - HomeVc
                    - MessageVc
                    - Discover
                    - Profile
            - 添加以上四个子控制器(封装一个公共的方法 -> 用于创建子控制器和添加)
    - 第三天下午内容总结
        - 自定义 HMTabBar (因为我们要显示一个撰写按钮)
            - 手写代码创建HMTabBar 需要实现 init(frame) init(coder)
            - init(coder)为什么(防止其他人使用时候 用于创建 sb xib)
        - 抽取 button 的 extension
        - @objc (使用 oc 的消息运行机制来调用方法)
        - 使用 Swift 中的协议和代理 实现 撰写按钮点击告知 MainVc(闭包|| 直接调用属性)
        - 通过遍历获取HMTabBar subviews 通过 class 获取 对应的 uibarbutton 设置 frame
        - class == 类名.self   || NSClassFromString("私用控件")
        - 自定义 UIBarButtonItem 
        - 创建 tempVc 
        - 自定义 HMNavC
            - 因为设置自定义的返回按钮手势失效
                - 解决 interactivePopGestureRecognizer?.delegate = self
            - 首页还可以滑动 造成不能在正常 push
                - 解决:gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
            - 按照业务逻辑 首页是 <首页的 tilte  以后显示的 < 返回
                - 解决方法 通过监听导航控制器的 push 方法(重写)
                    - 如果 count> 0 设置左侧按钮 
                        - 如果 count == 1  == 首页的 title
 
 
 
    - 公司人员分配
        - 客户
        - 老板(发钱)
        - 技术总监(PC 端, 前端, 手机移动端, 产品, UI, 后台, 测试, 文员, 运营)
        - 手机移动端
            - 苹果
            - 安卓
        - H5
            - 开发移动端界面 和 PC 端
 
        - UI 
            - 效果图, 标注图, 切图
        - 后台
            - java php .net
        - 测试 
            - 公司自己开发, jira(收费) bugfree(免费)
        - -文员
            - 数据的录入或者审核
        - 运营
            - 对公司的产品进行宣传
 
 
    - 公司开发流程(如果是给别人做产品)
 
        - 销售和甲方沟通 (成功)
        - 产品和甲方沟通 (形成产品文档)
            - 需求文档
            - 设置原型 (h5, 手机移动端, 后台, UI, 沟通 -> 方案可实施性)
        - UI出效果图(老板或者技术总监审核, 给甲方审核)
        - UI出标注图和切图
        - 移动端和 H5开始开发 后台也会跟进
        - 以上开发完成 
        - 测试人员测试
        - 甲方需要再次审核 -> 返回修改 -> 在审核 -> 直到封板
        - iOS
            - 第一次上线审核的周期 2周左右
            - 以后 一周左右
            - 什么情况会造成审核不过
                - 主线程卡死
                - 如果你上传的是安卓的效果图
                - 你发布的是关于公司的而使用个人账号发布
                - 你的 app 需要登录 (你没有提供测试账号)
                - 你当前 app 使用了支付 (如果是虚拟金币或者你会收费是基于苹果的 就需要强行使用内购)
                    - 如果使用内购 (如果单价100  苹果30  你70)
        - 邓白氏编码(15-20天) 成功
        - 填一些信息
            - 等待苹果回访电话
            
        - 账号 99 199
 
        - 开发人员可能会写项目开发文档
            - 你要写清楚你的项目模块和使用了哪些技术
            - 各种账号
 
 
 
 
    - 项目部署问题
        - 使用 github 码云
         - github 国外 翻墙 (访问慢) -> 收费
         -  速度快 而且是国内产品 主要是不收费
 
    - SSH  (了解)
        - 客户端 生成 rsa 秘钥 + 公钥
        - 然后把rsa公钥 给服务器
        - 项目成功
        - 客户端 随机成功一个 aes (秘钥)
        - 通过aes 把 项目 加密
        - 然后吧项目(通过 aes 加密后的)通过网络发送到远程服务器
        - 然后通过rsa吧 aes 加密 发送到服务器
        - 然后服务器rsa公钥 解密得到aes(非加密)
        - 通过 aes 解密加密后的项目
        - 然后保存项目

 */


